﻿using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Polly;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using NetMicro.Core.Extensions;
using NetMicro.Core.Ioc.Dependencies;
using NetMicro.Domains;
using NetMicro.Domains.Repositories;

namespace NetMicro.MongoProvider
{
    public interface IMongoDBRepository<TEntity, TKey> : IScoped where TEntity : EntityBase<TKey>, new()
    {
        #region 事务处理
        /// <summary>
        /// 开始事务
        /// </summary>
        /// <returns></returns>
        Task<IClientSessionHandle> StartTransactionAsync();

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        Task CommitTransactionAsync(IClientSessionHandle session);

        /// <summary>
        /// 终止事务
        /// </summary>
        /// <returns></returns>
        Task AbortTransactionAsync(IClientSessionHandle session);
        #endregion

        #region 新增
        /// <summary>
        /// 分表插入一条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        TKey Insert(TEntity t, object subTable = null, IClientSessionHandle session = null);

        /// <summary>
        /// 分表批量插入(分表)
        /// </summary>
        /// <param name="t">实体集合</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool InsertList(List<TEntity> t, object subTable = null, IClientSessionHandle session = null);


        /// <summary>
        /// 分表插入一条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<TKey> InsertAsync(TEntity t, object subTable = null, IClientSessionHandle session = null);

        /// <summary>
        /// 分表批量插入（异步）(分表)
        /// </summary>
        /// <param name="t">实体集合</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> InsertListAsync(List<TEntity> t, object subTable = null, IClientSessionHandle session = null);

        #endregion 新增

        #region 修改

        /// <summary>
        /// 修改单条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool Update(TEntity t, Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 修改多条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool UpdateMany(TEntity t, Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 修改多条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool UpdateList(List<TEntity> t, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 修改单条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> UpdateAsync(TEntity t, Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 修改多条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> UpdateManyAsync(TEntity t, Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 修改多条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> UpdateListAsync(List<TEntity> t, object subTable = null, IClientSessionHandle session = null);


        #endregion 修改

        #region 删除

        /// <summary>
        /// 逻辑删除一条数据(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool SoftDelete(TKey id, object subTable = null, IClientSessionHandle session = null);




        /// <summary>
        /// 逻辑删除多条数据(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool SoftDelete(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 物理删除一条数据（不推荐）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool Delete(TKey id, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 物理删除多条数据（不推荐）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        bool Delete(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);


        /// <summary>
        /// 异步逻辑删除一条数据（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> SoftDeleteAsync(TKey id, object subTable = null, IClientSessionHandle session = null);




        /// <summary>
        /// 异步逻辑删除多条数据（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> SoftDeleteAsync(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 异步物理删除一条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> DeleteAsync(TKey id, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 异步物理删除多条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);


        #endregion 删除

        #region 查询

        /// <summary>
        /// 查询单条记录
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        TEntity Get(Expression<Func<TEntity, bool>> filter = null, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, IClientSessionHandle session = null);



        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="limitCount">数量</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        List<TEntity> Query(Expression<Func<TEntity, bool>> filter = null, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, int limitCount = 0, IClientSessionHandle session = null);


        /// <summary>
        /// 分页获得集合
        /// 案例：GetList(t=>t.Level=="Info", t=>t, 1, 20, out rsCount)
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="orderBy">排序</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">条数</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        PagerList<TEntity> GetList(Expression<Func<TEntity, bool>> filter = null, Expression<Func<TEntity, object>> orderBy = null, int PageIndex = 1, int PageSize = 20, Expression<Func<TEntity, TEntity>> selector = null, object subTable = null, IClientSessionHandle session = null);

        /// <summary>
        /// Count
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        int Count(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);



        /// <summary>
        /// 查询单条记录(异步)
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter = null, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, IClientSessionHandle session = null);



        /// <summary>
        /// 查询集合(异步)
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="limitCount">数量</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> filter = null, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, int limitCount = 0, IClientSessionHandle session = null);


        /// <summary>
        /// 分页获得集合(异步)
        /// 案例：GetList(t=>t.Level=="Info", t=>t, 1, 20, out rsCount)
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="orderBy">排序</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">条数</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<PagerList<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> filter = null, Expression<Func<TEntity, object>> orderBy = null, int PageIndex = 1, int PageSize = 20, Expression<Func<TEntity, TEntity>> selector = null, object subTable = null, IClientSessionHandle session = null);

        /// <summary>
        /// Count (异步)
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        Task<int> CountAsync(Expression<Func<TEntity, bool>> filter = null, object subTable = null, IClientSessionHandle session = null);


        #endregion

        /// <summary>
        /// 验证集合文档(表)是否存在
        /// </summary>
        /// <returns></returns>
        bool CheckCollectionExists(object subTable = null);

        /// <summary>
        /// 验证集合文档(表)是否存在(异步)
        /// </summary>
        /// <returns></returns>
        Task<bool> CheckCollectionExistsAsync(object subTable = null);

        /// <summary>
        /// 获取MongoClient
        /// </summary>
        /// <returns></returns>
        public MongoClient GetMongoClient();

    }
}